package com.lancoo.ccas53.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lancoo.ccas53.entity.*;
import com.lancoo.ccas53.exception.BizException;
import com.lancoo.ccas53.mapper.StudentRetakeMapper;
import com.lancoo.ccas53.pojo.response.score.Retake;
import com.lancoo.ccas53.service.*;
import com.lancoo.ccas53.util.BatchInsert;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;


@Service("studentRetakeService")
public class StudentRetakeServiceImpl extends ServiceImpl<StudentRetakeMapper, StudentRetake> implements StudentRetakeService {


    @Resource
    private StudentRetakeMapper studentRetakeMapper;

    @Resource
    private TeachingClassService teachingClassService;

    @Resource
    private CourseService courseService;

    @Resource
    private StudentService studentService;

    @Resource
    private TeachingClassStudentService teachingClassStudentService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String syncStudentRetake(Integer taskId, String schoolId, String term, List<Retake> retakes) {
        List<StudentRetake> studentRetakes = new ArrayList<>();

        for (Retake retake : retakes) {
            studentRetakes.add(retake.toEntity(taskId, schoolId, term));
        }

        List<StudentRetake> addStudentRetakeList = new ArrayList<>();
        List<StudentRetake> deleteStudentRetakeList = new ArrayList<>();
        List<StudentRetake> list = this.lambdaQuery().eq(StudentRetake::getTaskId, taskId).list();

        Map<String, List<StudentRetake>> studentMap = studentRetakes.stream().collect(Collectors.groupingBy(StudentRetake::getBaseStudentId));

        studentMap.forEach((key, value) -> {
            List<StudentRetake> studentRetakeList = list.stream().filter(p -> p.getBaseCourseId().equals(key)).collect(Collectors.toList());
            if (CollUtil.isEmpty(studentRetakeList)) {
                addStudentRetakeList.addAll(value);
            } else {
                List<String> baseCourseIds = value.stream().map(StudentRetake::getBaseCourseId).collect(Collectors.toList());
                List<String> oldBaseCourseId = studentRetakeList.stream().map(StudentRetake::getBaseCourseId).collect(Collectors.toList());

                List<String> collect = oldBaseCourseId.stream().filter(p -> !baseCourseIds.contains(p)).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(collect)) {
                    List<StudentRetake> studentRetakes1 = studentRetakeList.stream().filter(p -> collect.contains(p.getBaseCourseId())).collect(Collectors.toList());
                    deleteStudentRetakeList.addAll(studentRetakes1);
                }
                baseCourseIds.removeAll(oldBaseCourseId);

                if (CollUtil.isNotEmpty(baseCourseIds)) {
                    List<StudentRetake> studentRetakes1 = value.stream().filter(p -> baseCourseIds.contains(p.getBaseCourseId())).collect(Collectors.toList());
                    addStudentRetakeList.addAll(studentRetakes1);
                }
            }
        });


        Consumer<List<StudentRetake>> studentConsumer = o -> studentRetakeMapper.addBatch(o);
        BatchInsert.batchSplitInsert(addStudentRetakeList, studentConsumer);

        if (CollUtil.isNotEmpty(deleteStudentRetakeList)) {
            List<TeachingClass> teachingClassList = teachingClassService.lambdaQuery().eq(TeachingClass::getTaskId, taskId).eq(TeachingClass::getTeachingClassType, 4).list();
            List<Course> courses = courseService.lambdaQuery().eq(Course::getTaskId, taskId).list();

            List<Long> teachingClasIds = teachingClassList.stream().map(TeachingClass::getTeachingClassId).collect(Collectors.toList());

            if (CollUtil.isNotEmpty(teachingClasIds)) {

                List<TeachingClassStudent> teachingClassStudentList = teachingClassStudentService.lambdaQuery()
                        .in(TeachingClassStudent::getTeachingClassId, teachingClasIds)
                        .eq(TeachingClassStudent::getFlag, 1).list();

                List<TeachingClassStudent> teachingClassStudents = new ArrayList<>();

                List<Student> students = studentService.lambdaQuery().eq(Student::getTaskId, taskId).list();
                deleteStudentRetakeList.forEach(o -> {
                    Student student = students.stream().filter(p -> p.getBaseStudentId().equals(o.getBaseStudentId())).findFirst().orElse(null);
                    if (ObjUtil.isNotNull(student)) {
                        Course course = courses.stream().filter(p -> p.getBaseCourseId().equals(o.getBaseCourseId())).findFirst().orElse(null);
                        if (ObjUtil.isNotNull(course)) {
                            List<Long> teachingClassIds = teachingClassList.stream().filter(p -> p.getCourseId().equals(course.getCourseId())).map(TeachingClass::getTeachingClassId).collect(Collectors.toList());
                            if (CollUtil.isNotEmpty(teachingClassIds)) {
                                List<TeachingClassStudent> collect = teachingClassStudentList.stream().filter(p -> teachingClassIds.contains(p.getTeachingClassId())
                                        && p.getStudentId().equals(student.getStudentId()) && p.getCourseId().equals(course.getCourseId())).collect(Collectors.toList());


                                if (CollUtil.isNotEmpty(collect)) {
                                    teachingClassStudents.addAll(collect);
                                }
                            }
                        }
                    }
                });

                if (CollUtil.isNotEmpty(teachingClassStudents)) {
                    List<Long> ids = teachingClassStudents.stream().map(TeachingClassStudent::getId).collect(Collectors.toList());
                    teachingClassStudentService.lambdaUpdate().in(TeachingClassStudent::getId, ids).remove();
                }
            }

        }
        return "重修学生已同步";
    }
}